package com.atguigu.tree.tread;

/**
 * @author durant
 * @create 2021-11-17 10:11
 */
public class ThreadBinaryTree {
    public static void main(String[] args) {
        HeroNode2 node1= new HeroNode2(1, "松江");
        HeroNode2 node3= new HeroNode2(3, "松江");
        HeroNode2 node6= new HeroNode2(6, "松江");
        HeroNode2 node8= new HeroNode2(8, "松江");
        HeroNode2 node10= new HeroNode2(10, "松江");
        HeroNode2 node14= new HeroNode2(14, "松江");
        node1.setLeft(node3);
        node1.setRight(node6);
        node3.setLeft(node8);
        node3.setRight(node10);
        node6.setLeft(node14);

        BinaryTree binaryTree =new BinaryTree(node1);
        binaryTree.threadedNodes();

        HeroNode2 left = node14.getLeft();
        int typeLeft = node1.getLeftType();
        int typeRight = node1.getLeftType();
        System.out.println("left:"+typeLeft+",right:"+typeRight);
//        System.out.println(left);
//        System.out.println("使用线索化的方式遍历线索化二叉树");
//        binaryTree.threadList();
    }
}

// 创建二叉树
class BinaryTree {
    private HeroNode2 root;

    // 为了实现线索化，需要创建要给指向当前结点的前驱节点的指针
    // 在递归进行线索化时，pre总是保留前一个节点
    private HeroNode2 pre = null;

    public HeroNode2 getRoot() {
        return root;
    }

    public void setRoot(HeroNode2 root) {
        this.root = root;
    }

    public BinaryTree(HeroNode2 root) {
        this.root = root;
    }

    public BinaryTree() {

    }
    public void threadedNodes(){
        this.threadedNodes(root);
    }
    // 遍历线索化二叉树的方法
    public void threadList(){
        HeroNode2 node = root;
        while (root != null){
            while (node.getLeftType() == 1){// 寻找开头的节点
                node = node.getLeft();
            }
            // 到这里找到了开头的点
            System.out.println(node);
            while (node.getRightType() == 1){// 如果当前节点的右指针指向的是后继节点，就一直输出
                node = node.getRight();
                System.out.println(node);
            }
            // 替换这个遍历的节点
            node = node.getRight();
        }
    }
    // 编写对二叉树进行中序线索化的方法
    public void threadedNodes(HeroNode2 node) {
        // 如果node为null，不能线索化
        if (node == null) {
            return;
        }
        // 线索化左子树
        threadedNodes(node.getLeft());
        // 线索化当前节点
        // 处理当前节点的前驱节点
        if (node.getLeft() == null) {
            node.setLeft(pre);
            node.setLeftType(1);
        }
        // 处理后继节点
        if (pre != null && pre.getRight() == null) {
            pre.setRight(node);
            pre.setRightType(1);
        }
        pre = node;
        // 线索化右子树
        threadedNodes(node.getRight());
        //
    }

    // 删除节点
    public void deleteNode(int no) {
        if (root != null) {
            if (root.getNo() == no) {// 如果root是空，那么将root删除，即将其置为空
                root = null;
            } else {
                root.deleteNode(no);
            }
        } else {
            System.out.println("空树不能删除");
        }
    }

    // 前序遍历
    public void preOrder() {
        if (this.root != null) {
            this.root.preList();
        } else {
            System.out.println("当前二叉树为空，不能遍历");
        }
    }

    // 中序遍历
    public void infixOrder() {
        if (this.root != null) {
            this.root.infixList();
        } else {
            System.out.println("当前二叉树为空，不能遍历");
        }
    }

    // 后序遍历
    public void lastOrder() {
        if (this.root != null) {
            this.root.lastList();
        } else {
            System.out.println("当前二叉树为空，不能遍历");
        }
    }

    public HeroNode2 preOrderSearch(int no) {
        if (root != null) {
            return root.preOrderSearch(no);

        } else {
            return null;
        }

    }

    public HeroNode2 infixOrderSearch(int no) {
        if (root != null) {
            return root.infixOrderSearch(no);

        } else {
            return null;
        }
    }

    public HeroNode2 lastOrderSearch(int no) {
        if (root != null) {
            return root.lastOrderSearch(no);

        } else {
            return null;
        }
    }
}

// 先创建node
class HeroNode2 {
    private int no;
    private String name;
    private HeroNode2 left;
    private HeroNode2 right;
    private int leftType;
    private int rightType;
    // 说明
    // 1.如果leftType == 0 表示指向的是左子树，如果是1表示指向的是前驱节点
    // 2.如果rightType == 0 表示指向的是右子树，如果是1表示指向的是后继节点

    public int getLeftType() {
        return leftType;
    }

    public void setLeftType(int leftType) {
        this.leftType = leftType;
    }

    public int getRightType() {
        return rightType;
    }

    public void setRightType(int rightType) {
        this.rightType = rightType;
    }



    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public HeroNode2 getLeft() {
        return left;
    }

    public void setLeft(HeroNode2 left) {
        this.left = left;
    }

    public HeroNode2 getRight() {
        return right;
    }

    public void setRight(HeroNode2 right) {
        this.right = right;
    }

    public HeroNode2(int no, String name) {
        this.no = no;
        this.name = name;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }

    // 递归删除节点
    public void deleteNode(int no) {
        /*
        1因为二叉树是单向的，所以我们是判断当前结点的子节点是不是需要删除的节点，而不是去判断当前点是不是需要删除的节点
        2如果当前节点 的左子节点不为空，并且左子节点就是需要删除的节点，那么就把this.left置为null，结束删除任务
        3如果当前节点的右子节点不为空，并且右子节点就是需要删除的节点，那么就把this.right置为null，结束删除任务
        4如果第2 3 步，没有删除节点，那么就需要向左子树进行递归
        5如果第4步没有删除，需要向右子树进行递归
        */
        if (this.left != null && this.left.no == no) {
            this.left = null;
            return;
        }
        // 3如果当前节点的右子节点不为空，并且右子节点就是需要删除的节点，那么就把this.right置为null，结束删除任务
        if (this.right != null && this.right.no == no) {
            this.right = null;
            return;
        }
        // 4如果第2 3 步，没有删除节点，那么就需要向左子树进行递归
        if (this.left != null) {
            this.left.deleteNode(no);
        }
        if (this.right != null) {
            this.right.deleteNode(no);
        }
    }

    // 前序遍历
    public void preList() {
        System.out.println(this);// 先输出父节点
        // 向左递归
        if (this.left != null) {
            this.left.preList();
        }
        // 向右递归
        if (this.right != null) {
            this.right.preList();
        }

    }

    // 中序遍历
    public void infixList() {
        // 向左递归
        if (this.left != null) {
            this.left.infixList();
        }
        //输出当前节点
        System.out.println(this);
        // 向右递归
        if (this.right != null) {
            this.right.infixList();
        }

    }

    // 后序遍历
    public void lastList() {
        // 向左递归
        if (this.left != null) {
            this.left.lastList();
        }
        // 向右递归
        if (this.right != null) {
            this.right.lastList();
        }
        //输出当前节点
        System.out.println(this);

    }

    // 前序查找
    public HeroNode2 preOrderSearch(int no) {
        // 比较当前节点
        if (this.no == no) {
            return this;
        }
        HeroNode2 heroNode = null;
        // 进入左节点
        if (this.left != null) {
            heroNode = this.left.preOrderSearch(no);

        }
        if (heroNode != null) {// 证明找到了，不进行右子树了
            // 退出就行了
            return heroNode;
        }
        if (this.right != null) {
            heroNode = this.right.preOrderSearch(no);
        }
        if (heroNode != null) {// 证明找到了
            // 退出就行了
            return heroNode;
        } else {
            return null;
        }
    }

    // 中序查找
    public HeroNode2 infixOrderSearch(int no) {
        System.out.println("中序查找找了几次");
        HeroNode2 heroNode = null;
        // 进入左节点
        if (this.left != null) {
            heroNode = this.left.infixOrderSearch(no);
        }
        if (heroNode != null) {// 证明找到了，不进行右子树了
            // 退出就行了
            return heroNode;
        }
        // 比较当前节点
        if (this.no == no) {
            return this;
        }
        if (this.right != null) {
            heroNode = this.right.infixOrderSearch(no);
        }
        if (heroNode != null) {// 证明找到了
            // 退出就行了
            return heroNode;
        } else {
            return null;
        }
    }

    // 后序查找
    public HeroNode2 lastOrderSearch(int no) {
//        System.out.println("后序查找找了几次");
        HeroNode2 heroNode = null;
        // 进入左节点
        if (this.left != null) {
            heroNode = this.left.lastOrderSearch(no);
        }
        if (heroNode != null) {// 证明找到了，不进行右子树了
            // 退出就行了
            return heroNode;
        }
        if (this.right != null) {
            heroNode = this.right.lastOrderSearch(no);
        }
        if (heroNode != null) {// 证明找到了，不进行右子树了
            // 退出就行了
            return heroNode;
        }
        // 比较当前节点
        if (this.no == no) {
            return this;
        }
        if (heroNode != null) {// 证明找到了
            // 退出就行了
            return heroNode;
        } else {
            return null;
        }
    }
}

